package repository

import entity.Activity
import entity.ActivityType
import entity.User
import org.hibernate.criterion.Restrictions

class ActivityRepositoryImpl : ActivityRepository {
    override fun findByActivityNameIgnoreCaseContainingAndCheckedTrue(name: String): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val rsName = Restrictions.like("activityName", "%$name%").ignoreCase()
            val rsCheck = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(rsName, rsCheck)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByActivityNameIgnoreCaseContainingAndCheckedTrue(
        name: String,
        pageable: Pageable
    ): Page<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val rsName = Restrictions.like("activityName", "%$name%").ignoreCase()
            val rsCheck = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(rsName, rsCheck)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            val list = cr.list().map { it as Activity }
            Page(
                content = list,
                pageable = pageable,
                totalElements = list.size.toLong()
            )
        }
    }

    override fun findByActivityTypeAndCheckedTrue(activityType: ActivityType): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val rsType = Restrictions.eq("activityType", activityType.toString())
            val rsCheck = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(rsType, rsCheck)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByActivityTypeAndCheckedTrue(activityType: ActivityType, pageable: Pageable): Page<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val rsType = Restrictions.eq("activityType", activityType.toString())
            val rsCheck = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(rsType, rsCheck)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            val list = cr.list().map { it as Activity }
            Page(
                content = list,
                pageable = pageable,
                totalElements = list.size.toLong()
            )
        }
    }

    // test : ok
    // modified: 21.5.8 chase
    override fun findByActivityCode(activityCode: String): Activity {
        return executeTransaction { session ->
            val criteria = session.createCriteria(Activity::class.java)
            criteria.add(Restrictions.eq("activityCode", activityCode))
            criteria.uniqueResult() as Activity
            // val ql = criteria.list()

            // if (ql.size > 0) {
            //     ql[0] as Activity
            // } else Activity().also { it.activityName = "no-result" }
        }
    }

    // test : ok

    override fun findByCheckedTrue(): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("checked", true))
            cr.list().map { it as Activity }
        }
    }
    // test : ok
    // modified: add totalElements-chase-21/05/13
    override fun findByCheckedTrue(pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.checked = :checked")
            query.setParameter("checked", true)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("checked", true))
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }
    // test : ok

    override fun findByCheckedFalse(): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("checked", false))
            cr.list().map { it as Activity }
        }
    }
    // test : ok
    // modified: add totalElements-chase-21/05/13
    override fun findByCheckedFalse(pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.checked = :checked")
            query.setParameter("checked", false)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("checked", false))
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }
    // test : ok

    override fun findByCheckedIsNull(): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.isNull("checked"))
            cr.list().map { it as Activity }
        }
    }
    // test : ok
    // modified: add totalElements-chase-21/05/13
    override fun findByCheckedIsNull(pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.checked is null")
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.isNull("checked"))
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }
    // test : ok

    override fun findByPublisher(publisher: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("publisher", publisher))
            cr.list().map { it as Activity }
        }
    }
    // test : ok
    // modified: add totalElements-chase-21/05/13
    override fun findByPublisher(publisher: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.publisher = :publisher")
            query.setParameter("publisher", publisher)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("publisher", publisher))
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByPublisherAndCheckedFalse(publisher: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.eq("checked", false)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByPublisherAndCheckedFalse(publisher: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.publisher = :publisher AND A.checked = :checked")
            query.setParameter("publisher", publisher)
            query.setParameter("checked", false)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.eq("checked", false)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByPublisherAndCheckedTrue(publisher: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByPublisherAndCheckedTrue(publisher: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.publisher = :publisher AND A.checked = :checked")
            query.setParameter("publisher", publisher)
            query.setParameter("checked", true)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByPublisherAndCheckedIsNull(publisher: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.isNull("checked")
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByPublisherAndCheckedIsNull(publisher: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.publisher = :publisher AND A.checked is null")
            query.setParameter("publisher", publisher)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("publisher", publisher)
            val crChecked = Restrictions.isNull("checked")
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByExaminer(examiner: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("examiner", examiner))
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByExaminer(examiner: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.examiner = :examiner")
            query.setParameter("examiner", examiner)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            cr.add(Restrictions.eq("examiner", examiner))
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByExaminerAndCheckedFalse(examiner: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.eq("checked", false)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByExaminerAndCheckedFalse(examiner: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.examiner = :examiner AND A.checked = :checked")
            query.setParameter("examiner", examiner)
            query.setParameter("checked", false)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.eq("checked", false)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByExaminerAndCheckedTrue(examiner: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByExaminerAndCheckedTrue(examiner: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.examiner = :examiner AND A.checked = :true")
            query.setParameter("examiner", examiner)
            query.setParameter("checked", true)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.eq("checked", true)
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }

    override fun findByExaminerAndCheckedIsNull(examiner: User): List<Activity> {
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.isNull("checked")
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.list().map { it as Activity }
        }
    }

    // modified: add totalElements-chase-21/05/13
    override fun findByExaminerAndCheckedIsNull(examiner: User, pageable: Pageable): Page<Activity> {
        val totalElements = executeTransaction {
            val query = it.createQuery("SELECT COUNT(A) FROM Activity A WHERE A.examiner = :examiner AND A.checked is null")
            query.setParameter("examiner", examiner)
            query.uniqueResult() as Long
        }
        return executeTransaction { session ->
            val cr = session.createCriteria(Activity::class.java)
            val crPublisher = Restrictions.eq("examiner", examiner)
            val crChecked = Restrictions.isNull("checked")
            val andExp = Restrictions.and(crPublisher, crChecked)
            cr.add(andExp)
            cr.sortBy(pageable)
            cr.setFirstResult(pageable.pageNumber * pageable.pageSize)
            cr.setMaxResults(pageable.pageSize)
            Page(
                content = cr.list().map { it as Activity },
                pageable = pageable,
                totalElements = totalElements
            )
        }
    }
}